/**
 * 
 */
package com.client;

import java.io.File;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.compress.archivers.ArchiveStreamFactory;

import com.tool.Log;
import com.tool.Parameter;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.compress.CompressUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * @author w_weizhen@sina.com
 * 
 */
public class StartDown 
{
    //数据是否发生变化
    private static Boolean change = false;
    
    //启动服务
    public static void run()
    {
        //定时更新文件
        CronUtil.schedule(Parameter.cron, new Task() {
            @Override
            public void execute() {
                down();
            }
        });
        // 支持秒级别定时任务
        CronUtil.setMatchSecond(true);
        CronUtil.start();
    }
    
    private static void down()
    {
        //默认数据没有变化
        change = false;
        
        //首先下载目录索引
        getIndexes();
        //如果下载失败不必向下执行
        if(!FileUtil.exist(Parameter.indexes_path))
        {
            Log.log("索引信息下载失败!");
            return;
        }
        //将索引文件转为json对象
        JSONObject datas = JSONUtil.readJSONObject(FileUtil.file(Parameter.indexes_path), CharsetUtil.CHARSET_UTF_8);
        for (Map.Entry<String, Object> entry : datas.entrySet()) 
        {
            //文件名称
            String key = entry.getKey();
            //文件信息
            JSONObject file_data = datas.getJSONObject(key);
            //下载文件
            dow(file_data);
        }
        
        //删除文件,如果本地文件不在索引文件中,则进行删除
        del();
        
        //是否是备份，如果是备份，则在文件发生变化后进行备份。
        if(Parameter.backups != null && Parameter.backups > 0 && change)
        {
            String backup_path = Parameter.local_file + "_backups";
            if(!FileUtil.exist(backup_path))
            {
                FileUtil.mkdir(backup_path);
            }
            File backup_file = FileUtil.file(backup_path + File.separator + DateUtil.format(DateUtil.date(), "yyyy-MM-dd-HH-mm-ss") + ".tar");
            CompressUtil.createArchiver(CharsetUtil.CHARSET_UTF_8, ArchiveStreamFactory.SEVEN_Z, backup_file)
            .add(FileUtil.file(Parameter.local_file))
            .finish()
            .close();
            
            File[] files = FileUtil.ls(backup_path);
            if(files != null && files.length > Parameter.backups)
            {
                for (int i = 0; i < files.length; i++)
                {
                    if((files.length - 1) >= Parameter.backups)
                    {
                        files[i].delete();
                    }
                }
            }
        }
    }
    
    //下载文件
    private static void dow(JSONObject file_data)
    {
        if(file_data == null || file_data.isEmpty())
        {
            Log.log("索引信息异常!" );
            return;
        }
        String name = file_data.getStr("name");
        long size = file_data.getLong("size");
        String md5 = file_data.getStr("md5");
        if(name == null || name == "" || size < 10)
        {
            Log.log("索引信息异常! file = " + file_data.toString());
            return;
        }
        
        //对比文件md5,不同下载,相同保持
        File local = new File(Parameter.local_file, name);
        if(local.exists() && Objects.equals(md5, SecureUtil.md5(local)))
        {
            Log.log("文件" + name + "无变化!不做下载");
            return;
        }
        try {
            String url = Parameter.server_uri + "/" + name;
            HttpUtil.downloadFile(url, FileUtil.file(local.getPath()));
            //下载文件，发生了变化
            change = true;
        } catch (Exception e) {
            Log.log(e.toString());
        }
    }
    
    //删除文件,如果本地文件不在索引文件中,则进行删除
    private static void del()
    {
        if(FileUtil.isDirEmpty(FileUtil.file(Parameter.local_file))) {return;}
        File[] files = FileUtil.ls(Parameter.local_file);
        JSONObject datas = JSONUtil.parseObj(new FileReader(Parameter.indexes_path).readString());
        for (int i = 0; i < files.length; i++) 
        {
            File file = files[i];
            if(!file.isFile()) {continue;}
            String name = file.getName();
            JSONObject data = datas.getJSONObject(name);
            if(data == null || data.isEmpty())
            {
                file.delete();
                //删除文件，发生了变化
                change = true;
            }
        }
    }
    //下载索引
    private static void getIndexes()
    {
        try {
            String url = Parameter.server_uri + "/" + Parameter.indexes;
            HttpUtil.downloadFile(url, FileUtil.file(Parameter.indexes_path));
            Log.log("下载索引: ("+url+"){"+Parameter.indexes_path+"}");
            Log.log(new FileReader(Parameter.indexes_path).readString());
        } catch (Exception e) {
            Log.log(e.toString());
        }
    }
    
}